/*
 * Copyright (c) 2009-2010 Cobalto Labs SAS
 *
 * Permission is hereby granted, free of charge, to any
 * person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the
 * Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the
 * Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice
 * shall be included in all copies or substantial portions of
 * the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
 * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Class to define a "package", maybe in the future can contain functionality
 */
var Co = new Class();

Co.Validation = new Class({
    /**
     * Constructor class
     * @param form the form to be validated, could be a string to indicate the id (recomended) or the element itself.
     */
    initialize:function(form) {
        this.form = $(form);
        this.form.on('submit', function(e) {
            var passed = this.inputs().filter(function(input) {
                return Co.Validation.validateInput(input);
            });
            if (passed.length != this.inputs().length) {
                e.stop();
            }
        });
    }

});

Co.Validation.messages = {};

Co.Validation.validators = {};
/**
 * Add a validator function
 * @param className the class name to be evaluated
 * @param message the message to be displayed
 * @param f validation function
 */
Co.Validation.addValidator = function(className, message, f) {
    Co.Validation.messages[className] = message;
    Co.Validation.validators[className] = f;
};

Co.Validation.addValidator('co-required', 'This is a required field', function(v) {
    return ((v == null) || (v.length == 0));
});

Co.Validation.addValidator('co-validate-number', 'Please enter a valid number in this field.', function(v) {
    return this['co-required'](v) || (isNaN(v) || /^\s+$/.test(v));
});

Co.Validation.addValidator('co-validate-digits', 'Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.', function(v) {
    return this['co-required'](v) || /[^\d]/.test(v);
});

Co.Validation.addValidator('co-validate-alpha', 'Please use letters only (a-z) in this field.', function(v) {
    return this['co-required'](v) || !/^[a-zA-Z]+$/.test(v);
});

Co.Validation.addValidator('co-validate-alphanum', 'Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.', function(v) {
    return this['co-required'](v) || /\W/.test(v);
});

Co.Validation.addValidator('co-validate-date', 'Please enter a valid date.', function(v) {
    var test = new Date(v);
    return this['co-required'](v) || isNaN(test);
});

Co.Validation.addValidator('co-validate-email', 'Please enter a valid email address. For example fred@domain.com .', function(v) {
    return this['co-required'](v) || ! /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(v)
});

Co.Validation.addValidator('co-validate-url', 'Please enter a valid URL.', function(v) {
    return this['co-required'](v) || !/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i.test(v)
});

/**
 * Validate a input control
 * @param input
 */
Co.Validation.validateInput = function(input) {
    input.nextSiblings(".co-error").each(function(div) {
        div.remove();
    });
    var result = 0;
    for (var name in Co.Validation.validators) {
        if (input.hasClass(name)) {
            if (defined(Co.Validation.validators[name]) && Co.Validation.validators[name](input.value)) {
                result++;
                var element = new Element('div', {html:input.title == '' ? Co.Validation.messages[name] : input.title}).addClass('co-error').setStyle('display:none');
                input.insert(element, 'after');
                new Fx.Fade(element).start();
            }
        }
    }
    return result == 0;
};